This article explains how to set up SSL termination for NGINX Plus and a load-balanced group of servers that accept TCP connections.
SSL termination means that NGINX Plus acts as the server-side SSL endpoint for connections with clients: it performs the decryption of requests and encryption of responses that backend servers would otherwise have to do. The operation is called termination because NGINX Plus closes the client connection and forwards the client data over a newly created, unencrypted connection to the servers in an upstream group. In release R6 and later, NGINX Plus performs SSL termination for TCP connections as well as HTTP connections.
First, you will need to obtain server certificates and a private key and put them on the server. A certificate can be obtained from a trusted certificate authority (CA) or generated using an SSL library such as OpenSSL.
To configure SSL termination, add the following directives to the NGINX Plus configuration:
To enable SSL, specify the ssl
parameter of the listen
directive for the TCP server that passes connections to an upstream server group:
stream {
server {
listen 12345 ssl;
proxy_pass backend;
…
}
}
To add SSL certificates, specify the path to the certificates (which must be in the PEM format) with the ssl_certificate
directive, and specify the path to the private key in the ssl_certificate_key
directive:
server {
…
ssl_certificate /etc/ssl/certs/server.crt;
ssl_certificate_key /etc/ssl/certs/server.key;
}
Additionally, the ssl_protocols
and ssl_ciphers
directives can be used to limit connections and to include only the strong versions and ciphers of SSL/TLS:
server {
…
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
}
The ssl_ciphers
directive tells NGINX to inform the SSL library which ciphers it prefers.
Implementing SSL/TLS can significantly impact server performance, because the SSL handshake operation (a series of messages the client and server exchange to verify that the connection is trusted) is quite CPU-intensive. The default timeout for the SSL handshake is 60 seconds and it can be redefined with the ssl_handshake_timeout
directive. We do not recommend setting this value too low or too high, as that might result either in handshake failure or a long time to wait for the handshake to complete:
server {
…
ssl_handshake_timeout 10s;
}
Creating a cache of the session parameters that apply to each SSL/TLS connection reduces the number of handshakes and thus can significantly improve performance. Caching is set with the ssl_session_cache
directive:
ssl_session_cache;
By default, NGINX Plus uses the built-in
type of the session cache, which means the cache built in your SSL library. This is not optimal, because such a cache can be used by only one worker process and can cause memory fragmentation. Set the ssl_session_cache
directive to shared
to share the cache among all worker processes, which speeds up later connections because the connection setup information is already known:
ssl_session_cache shared:SSL:1m;
As a reference, a 1-MB shared cache can hold approximately 4,000 sessions.
By default, NGINX Plus retains cached session parameters for five minutes. Increasing the value of the ssl_session_timeout
to several hours can improve performance because reusing cached session parameters reduces the number of time-consuming handshakes. When you increase the timeout, the cache needs to be bigger to accommodate the larger number of cached parameters that results. For the 4-hour timeout in the following example, a 20-MB cache is appropriate:
ssl_session_timeout 4h;
If the timeout length is increased, you need a larger cache to store sessions, for example, 20 MB:
server {
…
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 4h;
}
These lines create an in-memory cache of 20 MB to store session information, and instruct NGINX Plus to reuse session parameters from the cache for 4 hours after the moment they were added.
Session tickets are an alternative to the session cache. Session information is stored on the client side, eliminating the need for a server-side cache to store session information. When a client resumes interaction with the backend server, it presents the session ticket and re-negotiation is not necessary. Set the ssl_session_tickets
directive to on
:
server {
…
ssl_session_tickets on;
}
When using session tickets for an upstream group, each upstream server must be initialized with the same session key. It’s a best practice to change session keys frequently, we recommend that you implement a mechanism to rotate the shared key across all upstream servers:
server {
…
ssl_session_tickets on;
ssl_session_ticket_key /etc/ssl/session_ticket_keys/current.key;
ssl_session_ticket_key /etc/ssl/session_ticket_keys/previous.key;
}
stream {
upstream stream_backend {
server backend1.example.com:12345;
server backend2.example.com:12345;
server backend3.example.com:12345;
}
server {
listen 12345 ssl;
proxy_pass stream_backend;
ssl_certificate /etc/ssl/certs/server.crt;
ssl_certificate_key /etc/ssl/certs/server.key;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 4h;
ssl_handshake_timeout 30s;
…
}
}
In this example, the directives in the server
block instruct NGINX Plus to terminate and decrypt secured TCP traffic from clients and pass it unencrypted to the upstream group stream_backend
which consists of three servers.
The ssl
parameter of the listen
directive instructs NGINX Plus to accept SSL connections. When a clent requests a secure TCP connection, NGINX Plus starts the handshake process, which uses the PEM-format certificate specified by the ssl_certificate
directive, the certificate’s private key specified by the ssl_certificate_key
directive, and the protocols and cyphers listed by the ssl_protocols
and ssl_ciphers
directives.
As soon as the secure TCP connection is established, NGINX Plus caches the session parameters according to the ssl_session_cache
directive. In the example, the session cache is shared between all worker processes (the shared
parameter), is 20 MB in size (the 20m
parameter), and retains each SSL session for reuse for 4 hours (the ssl_session_timeout
directive).
To learn more about NGINX Plus, please see the descriptions of our commercial subscriptions.